<html>
<head>
    <title>Hatnote Listen to Wikipedia</title>
    <meta name="title" content="Hatnote Listen to Wikipedia">
    <meta name="description" content="Listen to recent changes on Wikipedia">
    <meta name="keywords" content="hatnote, listen, recent changes, sound, music, wikipedia, edits, visualization">
    <meta name="author" content="Stephen LaPorte and Mahmoud Hashemi">
    <link rel="stylesheet" type="text/css" href="css/nouislider.custom.css">
    <link rel="stylesheet" type="text/css" href="css/jquery.tagsinput.css">
    <script src="js/seedrandom.js" type="text/javascript"></script>
    <script src="js/jquery-1.9.1.min.js"></script>
    <script src="js/d3.min.js"></script>
    <script src="js/reconnecting-websocket.min.js" type="text/javascript"></script>
    <script src="js/app.js" type="text/javascript"></script>

    <script src="js/jquery.nouislider.min.js"></script>
    <script src="js/howler.min.js"></script>
    <script src="js/jquery.tagsinput.js" type="text/javascript"></script>
    <script>
    var global_mute = false;
    var global_volume = 50;
    var TAG_FILTERS = [];
    var DEBUG = false;
    $(function(){
      Howler.volume(global_volume * .01);

      $("#volumeControl").click(function() {
        if (!global_mute) {
          global_mute = false;
          Howler.mute();
          $("#volumeControl").css("background-position", "0 0");
        } else {
          global_mute = false;
          Howler.unmute();
          $("#volumeControl").css("background-position", "0 -46px");
        }
      });

      $("#volumeSlider").noUiSlider({
        range : [-99, 0],
        start : 0,
        handles : 1,
        step : 1,
        orientation : "horizontal",
        slide : function() {
          global_volume = 100 + $(this).val();
          var howler_volume = global_volume * 0.01;
          if (howler_volume <= 0.01) {
            Howler.mute();
          } else {
            Howler.unmute();
            Howler.volume(global_volume * .01);
          }
      }});


    });

    /* Settings
       ======== */

    var scale_factor = 5,
        note_overlap = 15,
        note_timeout = 300,
        current_notes = 0,
        max_life = 60000,
        DEFAULT_LANG = 'en';

    /* Colors
       ====== */

    var body_background_color = '#f8f8f8',
        body_text_color = '#000',
        svg_background_color = '#1c2733',
        svg_text_color = '#fff',
        newuser_box_color = 'rgb(41, 128, 185)',
        bot_color = 'rgb(155, 89, 182)',
        anon_color = 'rgb(46, 204, 113)',
        edit_color = '#fff',
        sound_totals = 51,
        total_edits = 0;

    /* Languages
       ========= */

    var langs = {
        'en': ['English', 'ws://wikimon.hatnote.com:9000'],
        'de': ['German', 'ws://wikimon.hatnote.com:9010'],
        'ru': ['Russian', 'ws://wikimon.hatnote.com:9020'],
        'uk': ['Ukrainian', 'ws://wikimon.hatnote.com:9310'],
        'ja': ['Japanese', 'ws://wikimon.hatnote.com:9030'],
        'es': ['Spanish', 'ws://wikimon.hatnote.com:9040'],
        'fr': ['French', 'ws://wikimon.hatnote.com:9050'],
        'nl': ['Dutch', 'ws://wikimon.hatnote.com:9060'],
        'it': ['Italian', 'ws://wikimon.hatnote.com:9070'],
        'sv': ['Swedish', 'ws://wikimon.hatnote.com:9080'],
        'ar': ['Arabic', 'ws://wikimon.hatnote.com:9090'],
        'fa': ['Farsi', 'ws://wikimon.hatnote.com:9210'],
        'he': ['Hebrew' , 'ws://wikimon.hatnote.com:9230'],
        'id': ['Indonesian', 'ws://wikimon.hatnote.com:9100'],
        'zh': ['Chinese', 'ws://wikimon.hatnote.com:9240'],
        'as': ['Assamese', 'ws://wikimon.hatnote.com:9150'],
        'hi': ['Hindi', 'ws://wikimon.hatnote.com:9140'],
        'bn': ['Bengali', 'ws://wikimon.hatnote.com:9160'],
        'pa': ['Punjabi', 'ws://wikimon.hatnote.com:9120'],
        'te': ['Telugu', 'ws://wikimon.hatnote.com:9165'],
        'ta': ['Tamil', 'ws://wikimon.hatnote.com:9110'],
        'ml': ['Malayalam', 'ws://wikimon.hatnote.com:9250'],
        'mr': ['Western Mari', 'ws://wikimon.hatnote.com:9130'],
        'kn': ['Kannada', 'ws://wikimon.hatnote.com:9170'],
        'or': ['Oriya', 'ws://wikimon.hatnote.com:9180'],
        'sa': ['Sanskrit', 'ws://wikimon.hatnote.com:9190'],
        'gu': ['Gujarati' , 'ws://wikimon.hatnote.com:9200'],
        'pl': ['Polish' , 'ws://wikimon.hatnote.com:9260'],
        'mk': ['Macedonian' , 'ws://wikimon.hatnote.com:9270'],
        'be': ['Belarusian' , 'ws://wikimon.hatnote.com:9280'],
        'sr': ['Serbian' , 'ws://wikimon.hatnote.com:9290'],
        'bg': ['Bulgarian' , 'ws://wikimon.hatnote.com:9300'],
        'hu': ['Hungarian', 'ws://wikimon.hatnote.com:9320'],
        'fi': ['Finnish', 'ws://wikimon.hatnote.com:9330'],
        'no': ['Norwegian', 'ws://wikimon.hatnote.com:9340'],
        'el': ['Greek', 'ws://wikimon.hatnote.com:9350'],
        'eo': ['Esperanto', 'ws://wikimon.hatnote.com:9360'],
	'pt': ['Portuguese', 'ws://wikimon.hatnote.com:9370'],
	'et': ['Estonian', 'ws://wikimon.hatnote.com:9380'],
	'ur': ['Urdu', 'ws://wikimon.hatnote.com:9390'],
	'ro': ['Romanian', 'ws://wikimon.hatnote.com:9400'],
	'hy': ['Armenian', 'ws://wikimon.hatnote.com:9410'],
        'wikidata': ['Wikidata' , 'ws://wikimon.hatnote.com:9220']
    }

    /*
       ============== */

    var w = window,
        d = document,
        e = d.documentElement,
        g = d.getElementsByTagName('#area svg')[0],
        width = w.innerWidth || e.clientWidth || g.clientWidth;
        height = (w.innerHeight  - $('#header').height())|| (e.clientHeight - $('#header').height()) || (g.clientHeight - $('#header').height());

    var celesta = [],
        clav = [],
        epm = 0,
        edit_times = [],
        SOCKETS = {},
        swells = [],
        all_loaded = false,
        s_titles = true,
        s_welcome = true,
        s_langs = [];

    var user_announcements = false;
    setTimeout(function() {
        user_announcements = true;
    }, 20000);

    $(function(){

        // Chrome 66 Autoplay Policy Compliance
        if (getChromeVersion() >= 66){
            if (Howler.ctx.state == 'suspended') {
                $('.about-link').prepend('<a class="unmute" href="#">enable sound?</a>');
            }
            $(document).click(function() { 
                Howler.ctx.resume().then($('.unmute').fadeOut());
            });
        }

        $('body').css('background-color', body_background_color)
        $('body').css('color', body_text_color)
        $('svg').css('background-color', svg_background_color)
        $('svg text').css('color', svg_text_color)
        // :(
        $('head').append('<style type="text/css">.newuser-label {fill:' + svg_text_color +
                         ';} .bot {fill:' + bot_color +
                         ';} .anon {fill:' + anon_color +
                         ';} .bot </style>');
        $('body').append('<div id="loading"><p>Loading sound files ...</p></div>')

        var svg = d3.select("#area").append("svg")
            .attr({width: width, height: height})
            .style('background-color', '#1c2733');

        var update_window = function() {
            width = w.innerWidth || e.clientWidth || g.clientWidth;
            height = (w.innerHeight  - $('#header').height())|| (e.clientHeight - $('#header').height()) || (g.clientHeight - $('#header').height());

            svg.attr("width", width).attr("height", height);
            if (epm_text) {
                epm_container.attr('transform', 'translate(0, ' + (height - 25) + ')')
            }
            update_tag_warning();
            /*rate_bg.attr("width", width).attr("height", height);*/
        }

        window.onresize = update_window;

        $('#welcome').click(make_click_handler($('#welcome'), 'nowelcomes')
        );
        $('#titles').click(
            make_click_handler($('#titles'), 'notitles')
        );
        $('#background_mode').click(
            function() {$("#area svg").toggle();}
        );
        $('#hide_rc_box').click(
            function() {$("#rc-log").toggle();}
        );

        $('#about-link').click(function(){
            // because we use window.location to set languages.
            $('html, body').animate({scrollTop:$(document).height()}, 'slow');
            return false;
        });

        // TODO: Volume slider?
        var loaded_sounds = 0
        var sound_load = function(r) {
            loaded_sounds += 1
            if (loaded_sounds == sound_totals) {
                all_loaded = true
                $('#loading').remove()
                console.log('Loading complete')
            } else {
                // console.log('Loading : ' + loaded_sounds + ' files out of ' + sound_totals)
            }
        }

        // load celesta and clav sounds
        for (var i = 1; i <= 24; i++) {
            if (i > 9) {
                fn = 'c0' + i;
            } else {
                fn = 'c00' + i;
            }
            celesta.push(new Howl({
                urls : ['sounds/celesta/' + fn + '.ogg',
                        'sounds/celesta/' + fn + '.mp3'],
                volume : 0.2,
                onload : sound_load(),
            }))
            clav.push(new Howl({
                urls : ['sounds/clav/' + fn + '.ogg',
                        'sounds/clav/' + fn + '.mp3'],
                volume : 0.2,
                onload : sound_load(),
            }))
        }

        // load swell sounds
        for (var i = 1; i <= 3; i++) {
            swells.push(new Howl({
                urls : ['sounds/swells/swell' + i + '.ogg',
                        'sounds/swells/swell' + i + '.mp3'],
                volume : 1,
                onload : sound_load(),
            }))
        }

        /*
        function testuser() {
            data = {user: 'Slaporte'}
            newuser_action(data, 'en', svg)
        }

        testuser()
        */

        for (lang in langs) {
            if (langs.hasOwnProperty(lang)) {
                if (lang == 'wikidata') {
                    $('#lang-boxes').append('<p><input type="checkbox" name="' + langs[lang][0] + '" id="' + lang + '-enable"/><label for="' + lang + '-enable">' + langs[lang][0] + ' <span class="conStatus" id="' + lang + '-status"></span></label></p>')
                } else {
                    $('#lang-boxes').append('<p><input type="checkbox" name="' + langs[lang][0] + '" id="' + lang + '-enable"/><label for="' + lang + '-enable">' + langs[lang][0] + ' Wikipedia <span class="conStatus" id="' + lang + '-status"></span></label></p>')
                }
                SOCKETS[lang] = new wikipediaSocket.init(langs[lang][1], lang, svg);
                var box = $('#' + lang + '-enable');
                if (box.is(':checked')) {
                    enable(lang)
                }
                box.click(make_click_handler(box, lang));
            }
        }

        enabled_langs = return_lang_settings();

        if (!enabled_langs.length) {
            enabled_langs.push(DEFAULT_LANG)
        }
        for (var i = 0; i < enabled_langs.length + 1; i ++) {
            var lang = enabled_langs[i];
            $('#' + lang + '-enable').prop('checked', true);
            if (SOCKETS[lang] && (!SOCKETS[lang].connection ||
                                  SOCKETS[lang].connection.readyState == 3)) {
                SOCKETS[lang].connect();
            }
        }
      $('#filter').tagsInput({
        height: '45px',
        width: '80%',
        'delimiter': [' ', ','],
        defaultText: 'Add a tag',
        defaultTextWidth: 100,
        unique: false,
        onChange: function() {
          TAG_FILTERS = [];
          $('.tag span').each(function(val) {
              var tag = $(this).text().trim().replace('#', '').toLowerCase();
              if($.inArray(tag, TAG_FILTERS) === -1){
                TAG_FILTERS.push(tag);
              }
          });
          update_tag_warning(svg);
          console.log('Watching for: ' + TAG_FILTERS)
        }
      });

    })
    </script>
<link href='css/style.css' rel='stylesheet' type='text/css'>
</head>
<body>
    <div id='header'>
      <span class="about-link">
        <span id="volumeWrapper" class="interface">
          <span id="volumeSlider" class="noUiSlider"></span>
        </span><a id="about-link" href="">about</a> &amp; <a href="http://blog.hatnote.com/" target="_blank">blog</a> &amp; <a href="https://twitter.com/hatnotable" target="_blank">twitter</a> &amp; <a href="https://itunes.apple.com/us/app/listen-to-wikipedia/id832934300" target="_blank">app</a></span>
      <h1>Listen to Wikipedia</h1>
    </div>
    <div id='area'></div>
    <div id='content'>
        <div class='bg'>
            <div id='rc-log-c'>
                <h3>Recent changes</h3>
                <ul id='rc-log'>
                </ul>
                 <div class="note">
                  <p id="edit_counter"></p>
                  <p>For more, see Wikipedia's RecentChanges pages for <a href="http://www.wikipedia.org/">each language</a>.</p>
                </div>
            </div>
        </div>
    </div>
    <div class="foot">
        <h3>Settings</h3>
        <p><input type="checkbox" name="welcome" id="welcome">
        <label for='welcome'>Hide new user announcements</label></p>
        <p><input type="checkbox" name="titles" id="titles">
        <label for='titles'>Hide article titles</label></p>
        <p><input type="checkbox" name="hide_rc_box" id="hide_rc_box">
        <label for="hide_rc_box">Hide recent changes console</label></p>
        <p><input type="checkbox" name="background_mode" id="background_mode">
        <label for="background_mode">Hide graphics for background listening</label></p>
        <h3>Languages</h3>
        <div id='lang-boxes'> </div>
        <div class='clear'><br/></div>
        <h3>Tags</h3>
        <p>Listen for edits with a hashtag in the edit summary. Try it yourself! To do this, enter a hashtag below, then go make an edit and the same tag in the <a href="https://en.wikipedia.org/wiki/Help:Edit_summary">edit summary</a> of your article. If you have tags here, you will only hear edits with those tags.</p>
        <p><input id="filter" type="text" value=""></p>
        <h3>About</h3>
        <p><a href='http://blog.hatnote.com/post/56856315107/listen-to-wikipedia'>Read more</a> about this project.</p>
        <p>Listen to the sound of Wikipedia's recent changes feed. Bells indicate additions and string plucks indicate subtractions. Pitch changes according to the size of the edit; the larger the edit, the deeper the note. Green circles show edits from <a href='http://en.wikipedia.org/wiki/Wikipedia:User_access_levels#Unregistered_users'>unregistered contributors</a>, and purple circles mark edits performed by <a href='http://en.wikipedia.org/wiki/Wikipedia:Bots'>automated bots</a>. You may see announcements for new users as they join the site, punctuated by a string swell. You can welcome him or her by clicking the blue banner and adding a note on their talk page.</p>
        <p>This project is built using <a href='http://d3js.org'>D3</a> and <a href='https://github.com/goldfire/howler.js'>HowlerJS</a>. It is based on <a href="http://bitlisten.com">BitListen</a> by <a href='https://www.maxlaumeister.com/'>Maximillian Laumeister</a>. Our source is <a href='https://github.com/hatnote/listen-to-wikipedia'>available on GitHub</a>, and you can read more about this project.</p>
        <p>Built by Hatnote, <a href='http://github.com/slaporte'>Stephen LaPorte</a> and <a href='http://github.com/mahmoud'>Mahmoud Hashemi</a>. For more, read about <a href="http://sedimental.org/hatnote_projects.html">the story behind Hatnote</a>.</p>
        <p class="small">This site uses <a href="http://www.google.com/analytics/">google analytics</a> to find out how many people visit it and some related information. You can <a href="https://tools.google.com/dlpage/gaoptout">opt out of google analytics</a> by installing a browser add-on.</p>
    </div>
    <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    ga('create', 'UA-40320359-1', 'hatnote.com');
    ga('send', 'pageview');
    </script>
</body>
</html>
